package se.sll.service.catalogue.common;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

/**
 * Parses an SQL script into statements.
 * 
 * @author Christer Palm, Nogui
 */
public class SqlScript {
	private final Reader iReader;
	private int iNextChar;

	public SqlScript(String aFilename) throws IOException {
		this(new File(aFilename));
	}

	public SqlScript(File aFile) throws IOException {
		this(new FileReader(aFile));
	}

	public SqlScript(Reader aReader) throws IOException {
		iReader = new BufferedReader(aReader);
		iNextChar = iReader.read();
	}

	public boolean hasNextStatement() {
		return peek() != -1;
	}

	public String nextStatement() {
		StringBuilder tStatement = new StringBuilder();
		try {
			while (true) {
				int tChar = get();
				if (tChar == -1) {
					break;
				} else if (tChar == '\'') {
					// Copy string literal
					do {
						tStatement.append((char) tChar);
						tChar = get();
					} while (tChar != '\'' && tChar != -1);
					if (tChar != -1) {
						tStatement.append((char) tChar);
					}
				} else if (tChar == '-' && peek() == '-') {
					// Skip -- comment
					while (peek() != '\n' && peek() != -1) {
						tChar = get();
					}
				} else if (tChar == '/' && peek() == '*') {
					// Skip /* comment
					while (!(tChar == '*' && peek() == '/') && tChar != -1) {
						// FIXME Handle nested comments
						tChar = get();
					}
					get(); // Skip '/'
				} else if (tChar == ';') {
					// Statement separator
					break;
				} else {
					tStatement.append((char)tChar);
				}
			}
			while (peek() == '\n' || peek() == ' ' || peek() == '\t') {
				get();
			}
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		return tStatement.toString().trim();
	}

	private int peek() {
		return iNextChar;
	}

	private int get() throws IOException {
		int tChar = iNextChar;
		iNextChar = iReader.read();
		return tChar;
	}
}
